package com.clei.utils;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 集合 util
 *
 * @author Y
 * @date 2023-12-25
 **/
public class CollectionUtil {
    /**
     * isEmpty
     *
     * @param collection collection
     * @param <T>        T
     * @return true/false
     */
    public static <T> boolean isEmpty(Collection<T> collection) {
        return null == collection || collection.isEmpty();
    }

    /**
     * isNotEmpty
     *
     * @param collection collection
     * @param <T>        T
     * @return true/false
     */
    public static <T> boolean isNotEmpty(Collection<T> collection) {
        return !isEmpty(collection);
    }

    /**
     * isEmpty
     *
     * @param map map
     * @param <K> K
     * @param <V> V
     * @return true/false
     */
    public static <K, V> boolean isEmpty(Map<K, V> map) {
        return null == map || map.isEmpty();
    }

    /**
     * isNotEmpty
     *
     * @param map map
     * @param <K> K
     * @param <V> V
     * @return true/false
     */
    public static <K, V> boolean isNotEmpty(Map<K, V> map) {
        return !isEmpty(map);
    }

    /**
     * size
     *
     * @param collection collection
     * @param <T>        T
     * @return size
     */
    public static <T> int size(Collection<T> collection) {
        return isEmpty(collection) ? 0 : collection.size();
    }

    /**
     * cut
     *
     * @param list          list
     * @param batchQuantity 单批元素数量
     * @param <T>           T
     * @return lists
     */
    public static <T> List<List<T>> cut(List<T> list, int batchQuantity) {
        if (isEmpty(list)) {
            return Collections.emptyList();
        }
        if (batchQuantity < 1) {
            batchQuantity = 1;
        }
        long bq = batchQuantity;
        int batchNum = (list.size() + batchQuantity - 1) / batchQuantity;
        return Stream.iterate(0, i -> i + 1).limit(batchNum)
                .map(i -> list.stream().skip(i * bq).limit(bq).collect(Collectors.toList()))
                .collect(Collectors.toList());
    }

    /**
     * mapCut
     *
     * @param list          list
     * @param batchQuantity 单批元素数量
     * @param <T>           T
     * @param <V>           V
     * @return lists
     */
    public static <T, V> List<List<V>> mapCut(List<T> list, Function<T, V> mapper, int batchQuantity) {
        if (isEmpty(list)) {
            return Collections.emptyList();
        }
        if (batchQuantity < 1) {
            batchQuantity = 1;
        }
        long bq = batchQuantity;
        int batchNum = (list.size() + batchQuantity - 1) / batchQuantity;
        return Stream.iterate(0, i -> i + 1).limit(batchNum)
                .map(i -> list.stream().skip(i * bq).limit(bq).map(mapper).collect(Collectors.toList()))
                .collect(Collectors.toList());
    }

    /**
     * cut
     *
     * @param list          list
     * @param batchQuantity 单批元素数量
     * @param <T>           T
     */
    public static <T> void cutAndRun(List<T> list, int batchQuantity, Consumer<List<T>> consumer) {
        if (isEmpty(list)) {
            return;
        }
        if (batchQuantity < 1) {
            batchQuantity = 1;
        }
        long bq = batchQuantity;
        int batchNum = (list.size() + batchQuantity - 1) / batchQuantity;
        for (int i = 0; i < batchNum; i++) {
            List<T> collect = list.stream().skip(i * bq).limit(bq).collect(Collectors.toList());
            consumer.accept(collect);
        }
    }
}
